package co.edu.udea.herbario.bl;

import co.edu.udea.herbario.dao.EjemplarDao;
import co.edu.udea.herbario.dto.Ejemplar;
import co.edu.udea.herbario.dao.cnf.FactoryDao;
import java.util.ArrayList;
import java.util.List;

/**
 * Clase que contiene la validacion del formato de los datos de entrada de los metodos de busqueda
 * de ejemplares
 * 
 * @author Marcela Colorado
 */
public class GeneracionLista
{
    //Creacion de un objeto tipo EjemplarDao a traves del FactoryDao
    EjemplarDao ejemplar = null;
    List<Ejemplar> ejemplares = null;

    public GeneracionLista()
    {
        ejemplar = FactoryDao.obtenerInstancia().getEjemplarDao();
    }

    /**
     * Consulta los ejemplares por familia, genero o nombre cientifico
     *
     * @param valor contiene el nombre de la familia, genero o nombre cientifico indicado como filtro
     * de busqueda
     * @param opcion hace referencia al tipo de busqueda que se desea realizar: por familia, genero
     * o nombre cientifico
     *
     * @return retorna una lista de ejemplares
     */
    public List<Ejemplar> obtenerEjemplares(int opcion, String valor)
    {
        //verifica que el campo valor contienga algun dato
        ejemplares = new ArrayList<Ejemplar>();
        
                if (this.tipoCadena(valor) == 1)
                {
                    switch(opcion)  //opcion indica que tipo de consulta se debe realizar
                    {
                    case 1: //consulta utilizando como criterio la familia indicada como parametro
                        try
                        {
                            //obtiene una lista con los ejemplares relacionados con la familia especificada
                            ejemplares = ejemplar.obtenerEjemplaresPorFamilia(valor);
                        }
                        catch(NullPointerException e)
                        {
                            break;
                        }
                        return ejemplares;

                    case 2: //consulta utilizando como criterio el genero indicado como parametro
                        try
                        {
                            //obtiene una lista con los ejemplares relacionados con el genero especificada
                            ejemplares = ejemplar.obtenerEjemplaresPorGenero(valor);
                        }
                        catch (NullPointerException e)
                        {
                        }
                        return ejemplares;

                    case 3: //consulta utilizando como criterio el nombre cientifico indicado como parametro
                        try
                        {
                            //obtiene una lista con los ejemplares relacionados con el nombre cientifico especificada
                            ejemplares = ejemplar.obtenerEjemplaresPorNombreCientifico(valor);
                        }
                        catch (NullPointerException e)
                        {
                         }
                        return ejemplares;
                    }
                }
        return ejemplares;
    }

     /**
     * Obtiene los ejemplares mediante el metodo de busqueda avanzada
     *
     * @param familia corresponde al nombre de la familia a la que pertenece el ejemplar
     * @param genero corresponde al nombre del genero al que pertenece el ejemplar
     * @param nombreCientifico corresponde al nombre cientifico asignado al ejemplar
     * @param colectorPrincipal corresponde al nombre la persona que recolecto el ejemplar
     * @param numeroColeccion corresponde al consecutivo asignado por el colector al ejemplar
     * @param codigoBarras corresponde al consecutivo asignado por el herbario al ejemplar
     * @param pais es el identificador del pais en el que se hallo el ejemplar
     * @param departamento es el identificador del departamento en el que se hallo el ejemplar
     * @param municipio es el identificador del municipio en el que se hallo el ejemplar
     *
     * @return retorna una lista de ejemplares
     */
    public List <Ejemplar> obtenerEjemplares(String familia, String genero, String nombreCientifico,
            String colectorPrincipal, String numeroColeccion, String codigoBarras, int pais,
            int departamento, int municipio)
    {
        //Valida que los datos ingresados no sean nulos y que cumplan con el formato requerido
        if((!"".equals(familia)&& this.tipoCadena(familia)==1) || (!"".equals(genero) &&
                this.tipoCadena(genero)==1) || (!"".equals(nombreCientifico) &&
                this.tipoCadena(nombreCientifico)==1) || (!"".equals(colectorPrincipal) &&
                this.tipoCadena(colectorPrincipal)==1) || (!"".equals(numeroColeccion)&&
                this.tipoCadena(numeroColeccion)==1) || (!"".equals(codigoBarras) &&
                this.validarCodigoBarras(codigoBarras)==1) || pais>0 ||departamento>0 || municipio>0)
        {
            //Recupera los ejemplares asociados a los parametros de busqueda
            ejemplares = ejemplar.obtenerListaEjemplares(familia, genero, nombreCientifico,
            colectorPrincipal, numeroColeccion, codigoBarras, pais, departamento, municipio);
        }

        return ejemplares;
    }

     /**
     * Consulta la ubicacion de los ejemplares de la misma especie y entrega: pais, departamento,
     * municipio, elevacion, latitud, longitud, fecha de coleccion, nombre del colector principal y
     * numero de coleccion
     *
     * @param esp corresponde al nombre de la especie
     *
     * @return retorna una lista con los ejemplares asociados a la especie indicada como parametro
     */
    public List<Ejemplar> obtenerUbicacionEspecie(String esp)
    {
        //Valida que los datos ingresados cumplan con el formato requerido
        if (this.tipoCadena(esp)==1)
        {
            //Obtiene los ejemplares asociados a la especie ingresada como parametro
            ejemplares = ejemplar.obtenerEjemplaresPorEspecie(esp);
        }

        return ejemplares;
    }

    /**
     * Metodo que identifica el tipo de cadena ingresada por el usuario
     *
     * @param cadena corresponde a la cadena de caracteres ingresada por el usuario
     *
     * @return un entero que indica el tipo de cadena, asi:
     * resultado = 1 --> cadena alfabetica
     * resultado = 2--> cadena numerica
     * resultado = 3 --> cadena de caracteres especiales
     * resultado = 4 --> cadena alfanumerica
     */
    private int tipoCadena(String cadena)
    {
        int resultado = 0;
        int cantidadLetras = 0;
        int cantidadNumeros = 0;
        int cantidadEspeciales = 0;
        int codigo = 0;
        int i;

        for(i = 0; i < cadena.length();i++)
        {
            codigo = (int) cadena.charAt(i);

            if ((64 < codigo && codigo < 91) || (96 < codigo && codigo < 123)|| codigo == 32)
            {
                cantidadLetras =  cantidadLetras + 1;
            }

            else if (47 < codigo && codigo < 58)
            {
                cantidadNumeros = cantidadNumeros + 1;
            }

            else
            {
                cantidadEspeciales = cantidadEspeciales + 1;
            }
        }
        
            if (cantidadLetras == cadena.length())
            {
               resultado = 1;
            }

            else if (cantidadNumeros == cadena.length())
                {
                    resultado = 2;
                }

            else if (cantidadEspeciales == cadena.length())
            {
                resultado = 3;
            }

            else if ((cantidadLetras + cantidadNumeros) == cadena.length())
            {
                resultado = 4;
            }

        return resultado;
    }

    /**
     * Comprueba si el codigo de barras tiene el formato: HUA0000000, ejemplares numerados desde el
     * HUA0000001 hasta el HUA2000000
     *
     * @param codBarras contiene la secuencia ingresada como parametro para el codigo de barras del ejemplar
     * 
     * @return
     */
    public int validarCodigoBarras(String codBarras)
    {
        int resultado = 0;
        char caracter;
        String letras = "";
        String consecutivo = "";
        int numeracion;
        int i;

        if(tipoCadena(codBarras) == 4 && codBarras.length()== 10)
        {
            for (i = 0; i < 3; i++)
                {
                    caracter = codBarras.charAt(i);
                    letras = letras + caracter;
                }

            if(letras.equals("HUA"))
            {
                for (i = 3; i< codBarras.length(); i++)
                {
                    consecutivo = consecutivo + codBarras.charAt(i);
                }

                numeracion = Integer.parseInt(consecutivo);

                if (numeracion > 0000000 && numeracion < 2000000)
                {
                    resultado = 1;
                    return resultado;
                }
            }

            else return resultado;
        }

        return resultado;
    }
}
